package com.analyse.stock.config;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池配置
 * corePoolSize：核心线程数，也就是线程池中的常驻线程，不管是否空闲都在池中，除非设置allowCoreThreadTimeOut，在超时时才会干掉核心线程
 * maximumPoolSize：线程池中允许的最大线程数
 * keepAliveTime：空闲线程的存活时间，这里是指除了核心线程外的空闲线程的存活时间，就算核心线程有空闲也不会被干掉
 * unit：keepAliveTime的单位
 * workQueue：任务队列，存提交但尚未执行的任务
 * threadFactory：创建线程的工厂
 * handler：拒绝策略，意思是当队列已满，并且最大线程数都在工作时执行拒绝策略
 *
 * 合理配置线程数
 * 1、CPU密集型
 * 线程个数=CPU核数+1
 * 2、IO密集型
 * 有两种：
 * 线程个数=CPU核数*2
 * 线程个数=CPU核数/1-阻塞系数，阻塞系数0.8-0.9
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "threadpool")
public class ThreadPoolConfig {
    /**
     * cpu 核心数量
     */
    public static final int CPU_NUM = Runtime.getRuntime().availableProcessors();

    private Integer priority;

    private Integer corePoolSize;

    private Integer maximumPoolSize;
    /**
     * 队列容量 (当前容量 + 剩余容量)
     */
    private Integer workQueue;

    private Integer keepAliveTime;

    public static ThreadPoolConfig defaultConfig() {
        ThreadPoolConfig poolConfig = new ThreadPoolConfig();
        poolConfig.setPriority(Thread.NORM_PRIORITY);
        poolConfig.setCorePoolSize(CPU_NUM);
        poolConfig.setMaximumPoolSize(CPU_NUM*2);
        poolConfig.setWorkQueue(100);
        poolConfig.setKeepAliveTime(60);
        return poolConfig;
    }

    public static String encode(ThreadPoolConfig config) {
        return JSONObject.toJSONString(config);
    }

    public static ThreadPoolConfig decode(String config) {
        JSONObject jsonConfig =JSONObject.parseObject(config);
        return JSONObject.toJavaObject(jsonConfig, ThreadPoolConfig.class);
    }

    /**
     * 往ioc容器中注入一个自定义的线程池
     * 核心线程数为30
     * 最大线程数为30
     * 临时线程等待任务时间为30s
     * 阻塞队列的长度为10
     * 拒绝策略为丢弃新任务
     * @return
     */
    @Bean("threadPoolExecutor")
    public ThreadPoolExecutor threadPoolExecutor(){
        return new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,
                TimeUnit.SECONDS,new ArrayBlockingQueue<>(workQueue),new ThreadPoolExecutor.AbortPolicy()
        );
    }
}
